//
//  Worker.m
//  WSPluginSwitcher
//
//  Created by Marc Bauer on 18.01.09.
//  Copyright 2009 nesiumdotcom. All rights reserved.
//

#import "Worker.h"

#define kWorkerSourcePathKey @"sourcePath"
#define kWorkerTargetPathKey @"targetPath"

@interface Worker (Private)
- (BOOL)_copyFileAtPath:(NSString *)sourcePath toPath:(NSString *)targetPath 
	error:(NSError **)error;
- (void)_informDelegateAboutError:(NSError *)error;
- (void)_informDelegateAboutSuccess:(NSString *)sourcePath;
- (void)_informDelegateAboutCompletion;
- (void)_restartBrowserWithName:(NSString *)name openURL:(NSURL *)aURL;
@end


@implementation Worker

@synthesize delegate=m_delegate;

#pragma mark -
#pragma mark Initialization & Deallocation

- (id)init
{
	if (self = [super init])
	{
		m_queue = [[NSMutableArray alloc] init];
	}
	return self;
}

- (void)dealloc
{
	[m_queue release];
	[super dealloc];
}



#pragma mark -
#pragma mark Public methods

- (void)awake
{
	[m_delegate workerDidAwake:self];
}

- (oneway void)addPathToQueue:(in bycopy NSString *)sourcePath 
	targetPath:(in bycopy NSString *)targetPath
{
	[m_queue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:
		sourcePath, kWorkerSourcePathKey, targetPath, kWorkerTargetPathKey, nil]];
}

- (oneway void)startCopying
{
	NSArray *queueCopy = [m_queue copy];
	for (NSDictionary *dict in queueCopy)
	{
		NSError *error = nil;
		BOOL success = [self _copyFileAtPath:[dict objectForKey:kWorkerSourcePathKey] 
			toPath:[dict objectForKey:kWorkerTargetPathKey] error:&error];
		if (success)
		{
			[self _informDelegateAboutSuccess:[dict objectForKey:kWorkerSourcePathKey]];
		}
		else
		{
			[self _informDelegateAboutError:error];
		}
		[m_queue removeObject:dict];
	}
	[queueCopy release];
	[self _informDelegateAboutCompletion];
}



#pragma mark -
#pragma mark Private methods

- (BOOL)_copyFileAtPath:(NSString *)sourcePath toPath:(NSString *)targetPath 
	error:(NSError **)error
{
	NSFileManager *fm = [NSFileManager defaultManager];
	// file already exists
	if ([fm fileExistsAtPath:targetPath])
	{
		// copy file to tmp location
		NSString *tmpPath = [targetPath stringByAppendingPathExtension:@"tmp"];
		// but first look, if we perhaps missed a tmp file in a former run
		if ([fm fileExistsAtPath:tmpPath] && [fm removeItemAtPath:tmpPath error:error])
		{
			return NO;
		}
		if (![fm copyItemAtPath:sourcePath toPath:tmpPath error:error])
		{
			return NO;
		}
		// remove existing file
		if (![fm removeItemAtPath:targetPath error:error])
		{
			// if it fails, cleanup
			[fm removeItemAtPath:tmpPath error:nil];
			return NO;
		}
		// finally rename tmp file
		if (rename([tmpPath fileSystemRepresentation], 
				[targetPath fileSystemRepresentation]) < 0) 
		{
			// if renaming fails, we try to move the file
			if (errno == EXDEV)
			{
				return [[NSFileManager defaultManager] movePath:tmpPath
					toPath:targetPath handler:nil];
			}
			return NO;
		}
		return YES;
	}
	return [fm copyItemAtPath:sourcePath toPath:targetPath error:error];
}

- (void)_informDelegateAboutError:(NSError *)error
{
	[m_delegate worker:self didFailWithError:error];
}

- (void)_informDelegateAboutSuccess:(NSString *)sourcePath
{
	[m_delegate worker:self didCopyFile:sourcePath];
}

- (void)_informDelegateAboutCompletion
{
	[m_delegate workerDidCompleteCopying:self];
}

@end